package net.xdclass.mybatis;

import net.xdclass.mybatis.annotation.ExtInsert;
import net.xdclass.mybatis.annotation.ExtParam;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Classname MyInvocationHandlerMybatis
 * @Description TODO
 * @Date 2022/11/26 16:02
 * @Created by sunhao
 */
public class MyInvocationHandlerMybatis implements InvocationHandler {

  private Object object;

  public MyInvocationHandlerMybatis(Object object) {
    this.object = object;
  }


  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println("进入代理类");
    ExtInsert extInsert = method.getDeclaredAnnotation(ExtInsert.class);
    if (extInsert != null) {
     return extInsert(extInsert,proxy,method,args);
    }
    return null;
  }

  private Object extInsert(ExtInsert extInsert, Object proxy, Method method, Object[] args) {
    Objects.requireNonNull(extInsert);
    String insertSql = extInsert.value();
    ConcurrentHashMap<Object, Object> paramsMap = paramsMap(proxy, method, args);
    String[] sqlInsertParameter = SQLUtils.sqlInsertParameter(insertSql);
    List<Object> sqlParams = sqlParams(sqlInsertParameter, paramsMap);
    String newSQL = SQLUtils.parameQuestion(insertSql, sqlInsertParameter);
    System.out.println("newSQL:" + newSQL + ",sqlParams:" + sqlParams.toString());
    return JDBCUtils.insert(newSQL, false, sqlParams);
  }

  private List<Object> sqlParams(String[] sqlInsertParameter, ConcurrentHashMap<Object, Object> paramsMap) {
    List<Object> sqlParams = new ArrayList<>();
    for (String paramName : sqlInsertParameter) {
      Object paramValue = paramsMap.get(paramName);
      sqlParams.add(paramValue);
    }
    return sqlParams;
  }

  private ConcurrentHashMap<Object, Object> paramsMap(Object proxy, Method method, Object[] args) {
    ConcurrentHashMap<Object, Object> paramsMap = new ConcurrentHashMap<>();
    Parameter[] parameters = method.getParameters();
    for (int i = 0; i < parameters.length; i++) {
      Parameter parameter = parameters[i];
      ExtParam extParam = parameter.getDeclaredAnnotation(ExtParam.class);
      if (extParam != null) {
        paramsMap.put(extParam.value(), args[i]);
      }
    }
    return paramsMap;
  }

  public Object extInsertSQL() {
    return object;
  }
}
